import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

import java.io.File;

public class TestQuery {
    String context1 = "Holle world";
    String context2 = "Holle java haha xixi world";
    String context3 = "Holle java Lucene world";

    String path = "E:\\demo\\Lucene\\query";
    //版本号
    Version matchVersion = Version.LUCENE_4_10_4;

    @Test
    public void testCreate() throws Exception {

        //先创建目录文件,存储索引文件
        Directory directory = FSDirectory.open(new File(path));
        //分析接口分词器
        StandardAnalyzer analyzer = new StandardAnalyzer();
        //配置对象
        IndexWriterConfig config = new IndexWriterConfig(matchVersion,analyzer);
        //索引写入对象
        IndexWriter writer = new IndexWriter(directory,config);

        //创建文档  写入对象
        Document doc1 = new Document();
        FieldType type = new FieldType();
        type.setIndexed(true);
        type.setStored(true);
        doc1.add(new Field("title","doc1",type));
        doc1.add(new Field("content",context1,type));

        //===============
        //创建文档  写入对象
        Document doc2 = new Document();

        doc2.add(new Field("title","doc2",type));
        doc2.add(new Field("content",context2,type));

        //===============
        //创建文档  写入对象
        Document doc3 = new Document();

        doc3.add(new Field("title","doc3",type));
        doc3.add(new Field("content",context3,type));

        //写入对象写入文档
        writer.addDocument(doc1);
        writer.addDocument(doc2);
        writer.addDocument(doc3);

        //将文件写入提交
        writer.commit();
        //关闭资源
        writer.close();

    }

    /**
     * 索引的查询
     * @param
     */
    public void testSearch1(String content) throws Exception{
        //先创建目录文件,存储索引文件
        Directory directory = FSDirectory.open(new File(path));
        //需要读取索引库里面的内容
        IndexReader r = DirectoryReader.open(directory);
        //创建索引读取 的对象
        IndexSearcher searcher = new IndexSearcher(r);

        //如果需要根据文本获取到查询对象,需要 导入queryParser类,将文本变成Query对象

        /**
         * f:需要查询的字段
         * a:分词器的 对象
         */
        //分析接口分词器
        Analyzer analyzer = new StandardAnalyzer();
        QueryParser parser = new QueryParser("content", analyzer);
        Query query = parser.parse(content);
        System.out.println(query.getClass());

        /**
         * search(query,n);
         * query  查询的对象,定义了查询那个字段,查询哪些内容
         * n:符合对象的前N条记录
         */
        TopDocs tds = searcher.search(query, 1000);
        System.out.println("查询命中数:" + tds.totalHits);
        ScoreDoc[] sds = tds.scoreDocs;
        ScoreDoc scoreDoc = null;
        Document doc = null;
        for (int i = 0;i < sds.length;i++) {
            scoreDoc = sds[i];
            doc = searcher.doc(scoreDoc.doc);
            System.out.println("文档的分数:" + scoreDoc.score+"title>>"+doc.get("title")+"content>>>>>>>>>>>>>>" + doc.get("content"));

            System.out.println("*************");
        }

    }

    /**
     * 索引的查询
     * @param query
     */
    public void testSearch2(Query query) throws Exception{
        //先创建目录文件,存储索引文件
        Directory directory = FSDirectory.open(new File(path));
        //需要读取索引库里面的内容
        IndexReader r = DirectoryReader.open(directory);
        //创建索引读取 的对象
        IndexSearcher searcher = new IndexSearcher(r);

        //如果需要根据文本获取到查询对象,需要 导入queryParser类,将文本变成Query对象

        /**
         * f:需要查询的字段
         * a:分词器的 对象
         */
        //分析接口分词器
        System.out.println(query);

        /**
         * search(query,n);
         * query  查询的对象,定义了查询那个字段,查询哪些内容
         * n:符合对象的前N条记录
         */
        TopDocs tds = searcher.search(query, 1000);
        System.out.println("查询命中数:" + tds.totalHits);
        ScoreDoc[] sds = tds.scoreDocs;
        ScoreDoc scoreDoc = null;
        Document doc = null;
        for (int i = 0;i < sds.length;i++) {
            scoreDoc = sds[i];
            doc = searcher.doc(scoreDoc.doc);
            System.out.println("文档的分数:" + scoreDoc.score+"title>>"+doc.get("title")+"content>>>>>>>>>>>>>>" + doc.get("content"));
            System.out.println("*************");
        }

    }

    /**
     *   *:*  第一个*匹配所有的字段
     *        第二个*是匹配所有的内容
     * @throws Exception
     */
    @Test
    public void testAll() throws Exception {

        testSearch1("*:*");

        System.out.println("-------------- ");


    }

    /**
     * 这是单词的查询
     * @throws Exception
     */
    @Test
    public void testWord() throws Exception {

        testSearch1("title:doc1");
        System.out.println("-------------- ");
        TermQuery query = new TermQuery(new Term("title", "doc1"));
        testSearch2(query);
    }

    /**
     * 段落的查询
     * @throws Exception
     */
    @Test
    public void testPrash() throws Exception {

        testSearch1("'java Lucene'");
        System.out.println("-------------- ");
        TermQuery query = new TermQuery(new Term("title", "doc1"));
        testSearch2(query);
    }

    /**
     * 模糊查找
     * ?  匹配一个字符
     * * 匹配多个字符
     * @throws Exception
     */
    @Test
    public void testWildCard() throws Exception {

        testSearch1("L*en?");
        System.out.println("-------------- ");
        TermQuery query = new TermQuery(new Term("title", "doc1"));
        testSearch2(query);
    }

    /**
     * ~1  容许错一个
     * @throws Exception
     */
    @Test
    public void testLike() throws Exception {

        testSearch1("jacc~2");
        System.out.println("-------------- ");

    }

    /**
     * 设置中间可以设置几个单词 ~后面的是可以容许插入几个单词
     * 如果是一个~就是可以插入任意的插入字符
     * @throws Exception
     */
    @Test
    public void testPrash2() throws Exception {

        testSearch1("\"java Lucene\"~2");
        System.out.println("-------------- ");
        TermQuery query = new TermQuery(new Term("title", "doc1"));
        testSearch2(query);
    }

}
